#include <QSize>
#include <QRectF>
#include <QObject>
#include <QHash>

#include <layer/tmslayer.h>
#include <provider/tmsprovider.h>
#include <utils/easygis.h>

namespace EasyGIS {

TmsLayer::TmsLayer(EasyGIS::TmsProviders provider,
                   const QString &id,
                   EasyGIS::MapCanvas *mapCanvas,
                   EasyGIS::CRS *crs)
    : MapLayer(id, crs, mapCanvas) {
  setProvider(TmsProviderFactory::create(provider));
}

double
TmsLayer::resolution() const {
  auto pd = dynamic_cast<const TmsProvider *>(&provider());
  auto sz = pd->tileSize();
  double length = crs().extent().width();
  double result = length / ((power2(zoomValue())) * sz.width());

#ifdef DEBUG
  qDebug() << "resolution=>" << result;
#endif

  return result;
}

QRectF
TmsLayer::extent() const {
  auto pd = dynamic_cast<const TmsProvider *>(&provider());
  QSize sz = pd->tileSize();

  int width = power2(zoomValue()) * sz.width();
  int height = power2(zoomValue()) * sz.height();

//#ifdef DEBUG
 // qDebug() << "layer extent=>{width:" << width << ", height:" << height << "}";
//#endif

  return {0, 0, static_cast<qreal>(width), static_cast<qreal>(height)};
}

void
TmsLayer::setZoomValue(int zoom) {
  int zoomValue{};
  if (zoom <= minZoom()) {
    zoomValue = minZoom();
  } else if (zoom >= maxZoom()) {
    zoomValue = maxZoom();
  } else {
    zoomValue = zoom;
  }

  mZoomValue = zoomValue;
}

bool
TmsLayer::parseTiles(const QRectF &rect, int zoom, QHash<QPoint, QString> &tiles, QSize &size) const {
  auto pd = dynamic_cast<const TmsProvider *>(&provider());
  auto tileSize = pd->tileSize();
  auto resolution = mCrs->extent().width() / ((power2(zoom)) * tileSize.width());

  auto crsLeftTop = mCrs->forward(PointXY(rect.topLeft()));
  auto crsRightBottom = mCrs->forward(PointXY(rect.bottomRight()));

  auto mapLeftTop = QPointF(crsLeftTop.x() / resolution, crsLeftTop.y() / resolution);
  auto mapRightBottom = QPointF(crsRightBottom.x() / resolution, crsRightBottom.y() / resolution);
  auto xMin = qFloor(mapLeftTop.x() / tileSize.width());
  auto xMax = qFloor(mapRightBottom.x() / tileSize.width());
  auto yMin = qFloor(mapLeftTop.y() / tileSize.height());
  auto yMax = qFloor(mapRightBottom.y() / tileSize.height());
  if((xMin > xMax) || (yMin > yMax)){
    qDebug() << "下载区边界错误";
    return false;
  }

  size.setWidth((xMax - xMin + 1) * tileSize.width());
  size.setHeight((yMax - yMin + 1) * tileSize.height());

  for (int i = xMin; i <= xMax; ++i) {
    for (int j = yMin; j <= yMax; ++j) {
      auto url = pd->tileUrl(PointXY(i, j), zoom);
      tiles.insert(QPoint(i - xMin, j - yMin), url);
    }
  }

  return true;
}

}
